#2021-10-28 @ Yanghuihui
#函数第五版
BoxVoiPlot1 <- function(data, Variable = 1, t.test = FALSE, oneway.test = FALSE,
                        Boxplot = FALSE, Boxtitle = "Box plot", Boxcolor = "plum",
                        Violinplot = FALSE, Viotitle = "Violin plot", Viocolor = TRUE,
                        VioPlusBox = FALSE,
                        filename = NULL, filetype = "pdf") 
#function:命名和自定义函数，BoxVoiPlot1为定义的函数名，data, variable等为函数所设置的参数
{
  #if...stop判定语句，如满足if括号内条件，则停止当前表达式并输出stop函数中的字符
  if(sum(is.na(data))>=1) 
    stop("your data have 'NA' value.")
  #如果数据中NA数量大于等于1,停止当前函数并输出"your data have 'NA' value."
  if(sum(is.null(data))>=1)
    stop("please input data again.")
  #如果数据中空值数量大于等于1，停止当前函数并输出"please input data again."
  if(!class(data) == "data.frame") 
    stop("data input should be data.frame format.")
  #如果判断数据格式不为数据框，停止当前函数并输出"data input should be data.frame format."
  if(!is.factor(data[,ncol(data)])){
    warning("the final column must be 'factor'.")
    as.factor(data[,ncol(data)])}
  #如果判断数据中列的格式不为因子，输出警告"the final column must be 'factor'."并将该列数据转换为因子。
  data1=data
  colnames(data)[ncol(data)]="group"
  colnames(data)[Variable]="value"
  if (Boxplot) {
  library(ggplot2)
  #library:加载R包，例如ggplot2包
  theme_set(theme_classic())
  #theme_set :主题设置
  #theme_classic():具有经典外观的主题，具有x和y轴线，没有网格线,类似还有theme_gray()
  #plot
  g<-ggplot(data,aes(group,value))
  #ggplot():用来构建初始绘图对象，以便之后的绘图
  #aes(class,cty):确定坐标数据，以所选数据中的class为x轴，cty为y轴
  p1 <-  g+geom_boxplot(varwidth = T,fill = Boxcolor)+
    labs(title = Boxtitle,
         x=colnames(data1)[ncol(data)],
         y=colnames(data1)[Variable])
  }
  if(Violinplot) {
   p2 <-  ggplot(data, aes(x = group,y = value))+
      #data 读取数据；mapping =aes 创建映射用于绘图，设置x轴和y轴调用的数据。
      geom_violin(if(Viocolor){aes(fill = group)})+
      #绘制几何对象~小提琴图，fill指填充颜色，按species不同分配填充
      #alpha调整透明度，colour调整边线颜色
      #自定义颜色+ scale_fill或colour_manual(values=c("#999999", "色号", "六位"))
      #使用RGB颜色模式
      #trim=FALSE用于不修尾
      #size设定线宽度，单位mm；group分组；
      #linetype设定线型(0 = 无线, 1 = 实线, 2 = 虚线, 3 = 点线, 4 = 点虚线, 5 = 长虚线, 6 = 双虚线)
      #加箱图，可用width=0.2设定宽度，透明度颜色等参数同上。
      geom_jitter(aes(shape = group))+
      #加抖动图，根据species选择不同形状。
      labs(title = Viotitle,
          x=colnames(data1)[ncol(data)],
          y=colnames(data1)[Variable])+
     if (VioPlusBox) {geom_boxplot(width=0.2)}
     
  }
  if (Boxplot & Violinplot) 
    #if判断式，如果同时绘制箱线图和小提琴图,则加载中括号内函数表达式。
    { 
    if(!require("patchwork")) install.packages("pacthwork",update = F,ask = F)
    #如果不能加载出 patchwork 包，则安装patchwork这个R包，且不进行更新。
    library(patchwork)
    p3=p1+p2
    #如果同时绘制 boxplot 和 violinplot，加载patchwork包并运行p1和p2函数，且两图形为横向布局
    if (is.character(filename) & length(filename) == 1) {
      filename0 = paste0(filename,"_Boxplot&Violinplot.",filetype) 
      #paste0:将paste0函数括号内全部字符连接变成一个字符串，且字符之间没有空格。
      ggsave(p3, filename = filename0)
      return(p3)
    }
  } else if (Boxplot) {
    if (is.character(filename) & length(filename) == 1) {
      filename1 = paste0(filename,"_Boxplot.",filetype) 
      ggsave(p1, filename = filename1)
    }
    return(p1)
  } else if  (Violinplot) {
    if (is.character(filename) & length(filename) == 1)
    #如果判断 filename 的格式为字符型且字符的数量为1，则加载中括号内函数表达式
    {
      filename2 = paste0(filename,"_Violinplot.",filetype) 
      ggsave(p2, filename = filename2)
    }
    return(p2)
  } else{print("原来你不想画图,只想进行统计检验噢！")}
  
if(length(levels(as.factor(as.character(data[,ncol(data)]))))>2) 
  {
  if (oneway.test) {summary(aov(value ~ group, data))}
#aov函数指对数据进行单因素方差分析，分析data数据中value与group变量的关系
  }else{
  if (t.test) {t.test(value ~ group, data)}
#t.test函数指对数据进行t检验，分析data数据中value与group变量之间是否存在显著差异。
  }
}
#一、使用内置数据 PlantGrowth：植物在3种不同光照强度下生长的重量。
#（1）选择两组数据（control 组和 treat2 组）作为输入数据：
twogroup=PlantGrowth[c(1:10,21:30),]
#1-1 不画图，只进行单因素t检验;
BoxVoiPlot1(data = twogroup, t.test = T) 

#1-2 画 Boxplot 和 Violinplot，并保存为pdf格式;
BoxVoiPlot1(data = twogroup, Boxplot = T, Boxtitle = "Box plot", Boxcolor = "plum",
            Violinplot = T, Viotitle = "Violin plot", Viocolor = T, 
            filename = "PlantGrowth2", filetype = "pdf") 

#（2） 将三组数据（control 组、treat1 组和 treat2 组）
#2-1 不画图，进行单因素方差分析;
BoxVoiPlot1(data = PlantGrowth, oneway.test = TRUE)

#2-2 画 Boxplot 和 Violinplot，并保存为png格式;
BoxVoiPlot1(PlantGrowth, Boxplot = T, Boxtitle = "Box plot", Boxcolor = "grey",
            Violinplot = T, Viotitle = "Violin plot", Viocolor = F,
            filename = "PlantGrowth3", filetype = "png") 
#我们换个颜色,换个title,
BoxVoiPlot1(PlantGrowth, Boxplot = T, Violinplot = T,
            Boxtitle = "Box plot of PlantGrowth", Boxcolor = "plum",
            Viotitle = "Violin plot of PlantGrowth", Viocolor = T,
            filename = "PlantGrowth3", filetype = "png") 



#二、我们换一个内置数据集 iris：3种花朵的花萼长宽。
#(1) 画一个单独的 Violinplot 叠加 Boxplot 
BoxVoiPlot1(data = iris, Violinplot = T, 
            Viotitle = "Flowers' sepal length", 
            Viocolor = T,VioPlusBox = T)

BoxVoiPlot1(data = iris, Variable = 2, 
            Boxplot = T, Boxtitle = "Flowers' sepal width", Boxcolor = "plum",
            Violinplot = T, Viotitle = "Flowers' sepal width", Viocolor = T,
            VioPlusBox = T, filename = "iris", filetype = "png")
#可以把data换成你们自己的数据试试
#第五版代码放在gitee上啦~点击下方链接↓
#https://gitee.com/yhhhygge/r_homework

